Fix Update Packages workflow failures; add Gradle and Mix ecosystem support - #65
Merged
einari merged 3 commits intoAug 14, 2026
Merged
Conversation
…x support
Three bugs were causing the daily Update Packages workflow to fail
across most of the org:
- Yarn Berry auto-detects GitHub Actions' CI=true and defaults installs
to immutable, so the yarn install that's supposed to write the
lockfile after npm-check-updates bumps package.json refuses to do so
("lockfile would have been modified... explicitly forbidden"). Set
YARN_ENABLE_IMMUTABLE_INSTALLS: false for that step.
- npm-check-updates was bumping typescript across its 6->7 rewrite,
which restructured the published package layout; Yarn Berry's builtin
compat/typescript patch hasn't been updated for it and crashes on
install. Excluded typescript from the automatic bump until Yarn ships
a fix (Fundamentals, Components, Workshops, Chronicle.TypeScript were
all hitting this).
- `dotnet package update` hard-aborts with no changes applied whenever
a package has different centrally-managed versions per target
framework (e.g. Arc deliberately pins System.Text.Json differently
for net8.0/net9.0 vs net10.0 via conditional Directory.Packages.*.props
imports, working around a Chronicle bug). That's a legitimate,
intentional setup the command just can't reconcile - now treated as a
soft skip instead of a hard failure.
Also adds Gradle (Kotlin/JVM) and Mix (Elixir) as detected ecosystems,
alongside the existing NuGet/NPM support:
- Gradle: detected via a root gradlew + settings/build.gradle(.kts).
Runs `./gradlew useLatestVersions` (gradle-versions-plugin +
gradle-use-latest-versions-plugin, which the target repo must declare
itself - see the companion Chronicle.Kotlin PR) then `./gradlew build`
to verify.
- Mix: detected via a mix.exs up to 3 directories deep (Elixir repos
here nest the package rather than rooting it, e.g.
Source/chronicle/mix.exs), ignoring deps/_build. Runs `mix deps.update
--all` (respects the ~> constraints already in mix.exs, same
safety margin NuGet/NPM don't have) then `mix compile` to verify.
Both new ecosystems follow the same pattern as NuGet/NPM: only commit
and push if the post-update build actually succeeds.
Live-tested against Arc and hit a second, different exit-3 failure mode that the text-match alone didn't cover: a plain NU1109 downgrade conflict (not the "not supported by this command" message), apparently from the command bumping one centrally-pinned package without correctly co-updating a transitively-pinned dependency of it. Same exit code (3), same "no changes written to disk" behavior, same fix.
Live-tested against Arc and found a third latent bug, previously masked by the NuGet exit-3 failure: this workflow built .NET before installing NPM dependencies, but Arc's ProxyGenerator.Specs.csproj has an MSBuild target that shells out to `yarn build`, so `dotnet build` failed with "This package doesn't seem to be present in your lockfile" - node_modules simply didn't exist yet. Reordered so every ecosystem's setup + dependency-update runs first, then every ecosystem's build runs afterward, regardless of which ecosystems are actually detected. This also fixes the equivalent latent risk for Gradle/Mix repos with cross-ecosystem build-time dependencies, not just the one now-visible NuGet+NPM case.
einari
deleted the
fix/update-packages-yarn-immutable-dotnet-tfm-gradle-elixir
branch
August 14, 2026 09:57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's broken today
The daily "Update Packages" workflow is failing across most of the org. Diagnosed each failure individually across ~10 affected repos; three root causes are fixable here in the shared workflow:
CI=true, which makes Yarn Berry default to immutable installs. Theyarn installmeant to write the lockfile afternpm-check-updatesbumpspackage.jsonrefuses ("lockfile would have been modified... explicitly forbidden").npm-check-updates -ujumpstypescriptacross its 6→7 rewrite (new internal package layout). Yarn Berry's builtincompat/typescriptpatch hasn't caught up and crashes on install.dotnet package updatehard-aborts on per-TFM version divergence (Arc): exits non-zero with zero changes applied whenever a package has different centrally-managed versions per target framework — which is exactly what Arc's conditionalDirectory.Packages.NET8-9.propssetup does deliberately (documented workaround for a Chronicle bug). The command can't reconcile that, so it's failed the same way every day with nothing anyone can do about it via NuGet alone.(Other failures — ProtocolGeneration, VerticalSlices, cli — were genuine breaking major-version bumps in application code, not workflow bugs; fixed directly in those repos: Cratis/ProtocolGeneration#8, Cratis/VerticalSlices#13, Cratis/cli#71.)
Fixes
YARN_ENABLE_IMMUTABLE_INSTALLS: falseon the post-ncuyarn installstep.typescriptfrom the automatic bump (-x typescript) until Yarn ships a compat-patch update for the new TS7 layout.dotnet package update's "is not supported by this command" (per-TFM divergence) as a soft skip instead of a hard failure.New: Gradle (Kotlin/JVM) and Mix (Elixir) support
Adds two new detected ecosystems alongside the existing NuGet/NPM:
gradlew+settings.gradle(.kts)/build.gradle(.kts). Runs./gradlew useLatestVersions(viagradle-versions-plugin+gradle-use-latest-versions-plugin, which the target repo declares itself — companion PR: Enable automated dependency updates via gradle-versions-plugin Chronicle.Kotlin#47) then./gradlew buildto verify.mix.exsup to 3 directories deep (Elixir repos here nest the package, e.g.Source/chronicle/mix.exs, rather than rooting it), ignoringdeps//_build/. Runsmix deps.update --all(respects the~>constraints already declared inmix.exs) thenmix compileto verify.Both follow the existing NuGet/NPM pattern: only commit and push if the post-update build actually succeeds.
To take effect, Chronicle.Kotlin needs Cratis/Chronicle.Kotlin#47 merged first (declares the two Gradle plugins this relies on). Chronicle.Elixir needs no repo-side changes —
mix.exsconstraints there are already loose enough formix deps.update --allto work as-is (verified locally). Chronicle itself is NuGet-only and already works; no changes needed there.Test plan
python3 -c "import yaml; yaml.safe_load(open(...))")dotnet package updateper-TFM abort locally against a real clone and confirmed the new soft-skip branch matches the actual error textuseLatestVersions+ build cycle locally against a real Chronicle.Kotlin clone (including the stable-only filter correctly skipping a real prerelease build)deps.update --all+compilecycle locally against a real Chronicle.Elixir clone